﻿using QxFramework.Core;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using App.Common;

public class MissionManager : LogicModuleBase,IMissionManager
{
    private int _startRoom;
    private int _clearRoom;
    private int _lastRoom;
    private float _timeScale;
    private List<string> _doorsName;
    private MapEditorBase.RoomStatue _roomStatue;
    public void InitMission(string mapName)
    {
        _doorsName = new List<string>();
        _clearRoom = 0;
        _delayCount = 120;
        _timeScale = Time.timeScale;
        foreach (var item in GameMgr.Get<IMapManager>().GetMapEditor().mapRooms)
        {
            if (item.Value.mapID == 0)
                _startRoom = item.Value.roomID;
        }
        UIManager.Instance.Open("OperationWindowUI", 2, args: new DialogWindowUI.DialogWindowUIArg("操作说明"));
        UIManager.Instance.Open("OperationCommandUI",1);
        UIManager.Instance.Open("DebugCommandUI", 1);
        InitPlayerSpawner();
        _initFlag = true;
    }
    private int _delayCount;
    private bool _initFlag = false;
    public override void Update()
    {
        UnityEngine.SceneManagement.Scene scene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
        if (scene.name == "MapScene")
            return;
        if (!_initFlag)
        {
            return;
        }
        int roomID = CheckPlayerRoom(); 
        if (roomID != -1)
        {
            UpdateRoomStatue(roomID);
            _delayCount--;
            CheckMenu();

            if (Time.timeScale == 0 && !UIManager.Instance.FindUI("DialogWindowUI"))
                Time.timeScale = _timeScale;
            if (_delayCount <= 0)
            {
                CheckPlayerAlive();
            }
            if (_roomStatue == MapEditorBase.RoomStatue.Enemy && _delayCount <= 0)
            {
                CheckRoomEnemy(roomID);
                _delayCount = 180;
            }
            if (_roomStatue == MapEditorBase.RoomStatue.Challenge && _delayCount <= 0)
            {
                Debug.Log("ChooseChallenge!");
                InitChallengeEnemy(roomID);
                InitDoor(roomID);
                _delayCount = 180;
            }

        }
        else
            _delayCount = 180;

    }
    /// <summary>
    /// 检查是否呼出菜单
    /// </summary>
    private void CheckMenu()
    {
        if ((InputManager.Instance.ESC(0) || InputManager.Instance.ESC(1)) && !UIManager.Instance.FindUI("DialogWindowUI"))
        {
            Time.timeScale = 0;
            var list = new List<string>() { "继续", "退出" };
            var action = new List<Action>();
            action.Add(() => { UIManager.Instance.Close("DialogWindowUI"); Time.timeScale = _timeScale; Cursor.visible = false; });
            action.Add(() => { UIManager.Instance.Close("DialogWindowUI");
#if UNITY_EDITOR
                UnityEditor.EditorApplication.isPlaying = false;
#else
        Application.Quit();
#endif
            });
            UIManager.Instance.Open("DialogWindowUI", 3, args: new DialogWindowUI.DialogWindowUIArg("提示", "游戏暂停中，您可以选择继续游戏或退出游戏。", null, list, action));
        }
        if (Time.timeScale == 0 && !UIManager.Instance.FindUI("DialogWindowUI"))
            Time.timeScale = _timeScale;
    }
    /// <summary>
    /// 检查玩家是不是活着
    /// </summary>
    private void CheckPlayerAlive()
    {
        bool alive = false;
        foreach (var item in GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas)
        {
            alive |= item.PlayerMono.HPData.HPValue > 0;
        }
        if (!alive && !UIManager.Instance.FindUI("DialogWindowUI"))
        {
#if UNITY_EDITOR
            UnityEditor.EditorApplication.isPlaying = false;
#else
        Application.Quit();
#endif
//             Cursor.visible = true;
//             Action act = new Action(() =>
//             {
//                 UIManager.Instance.Close("DialogWindowUI");
// #if UNITY_EDITOR
//                 UnityEditor.EditorApplication.isPlaying = false;
// #else
//         Application.Quit();
// #endif
//             });
//             UIManager.Instance.Open("DialogWindowUI", 3, args: new DialogWindowUI.DialogWindowUIArg("提示", "你死啦，可以结束游戏了。", null, "退出",act));
        }
    }
    /// <summary>
    /// 检测玩家当前所在房间
    /// </summary>
    /// <returns></returns>
    private int CheckPlayerRoom()
    {
        for (int i = 0; i < GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas.Count; i++)
        {
            var roomID = GetPlayerRoom(i);
            if (roomID == -1)
                continue;
            _lastRoom = roomID;
            if (GameMgr.Get<IMapManager>().GetCertainRoom(roomID).roomStatue == MapEditorBase.RoomStatue.Unknown)
            {
                _clearRoom++;
                SetRoomStatue(roomID);
                var pos = GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[i].PlayerMono.Position;
                float tempX = (pos.x + 1.25f) * 2;
                float tempY = (pos.y + 1.25f) * 2;
                int x = ((int)(tempX / 5) + (tempX < 0 ? -1 : 0)) * 5;
                int y = ((int)(tempY / 5) + (tempY < 0 ? -1 : 0)) * 5;
                var ground = GameMgr.Get<IMapManager>().GetCertainGround(y,x).position;
                for (int k = 0; k < GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas.Count; k++)
                {
                    if (GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[i].PlayerMono.HPData.HPValue == 0)
                        continue;
                    //if ((k != i) && (GetPlayerRoom(k) != roomID))
                    GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[k].PlayerMono.Position = ground;
                }
                return roomID;
            }
            return roomID;
        }
        return -1;
    }
    private int GetPlayerRoom(int playerID)
    {
        var pos = GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[playerID].PlayerMono.Position;
        float tempX = (pos.x + 1.25f) * 2;
        float tempY = (pos.y + 1.25f) * 2;
        int x = ((int)(tempX / 5) + (tempX < 0 ? -1 : 0)) * 5;
        int y = ((int)(tempY / 5) + (tempY < 0 ? -1 : 0)) * 5;
        var roomID = GameMgr.Get<IMapManager>().GetRoomID(y, x);
        return roomID;
    }
    /// <summary>
    /// 得到当前房间的状态
    /// </summary>
    /// <param name="roomID"></param>
    /// <returns></returns>
    private MapEditorBase.RoomStatue GetRoomStatue(int roomID)
    {
        int mapID = GameMgr.Get<IMapManager>().GetCertainRoom(roomID).mapID;
        int statue = UnityEngine.Random.Range(0, 101);
        string[] prob = Data.Instance.TableAgent.GetStrings("AllRoom", mapID.ToString(), "RoomStatue");
        int p = 0;
        for (int i = 0; i < prob.Length; i++)
        {
            p += int.Parse(prob[i]);
            if (statue <= p)
            {
                return (MapEditorBase.RoomStatue)i;
            }
        }
        return MapEditorBase.RoomStatue.Empty;
    }
    /// <summary>
    /// 随机当前房间的状态
    /// </summary>
    /// <param name="roomID"></param>
    private void SetRoomStatue(int roomID)
    {
        MapEditorBase.RoomStatue roomStatue = GetRoomStatue(roomID);
       switch (roomStatue)
        {
            case MapEditorBase.RoomStatue.Enemy:
                InitEnemy(roomID);
                InitDoor(roomID);
                _delayCount = 200;
                GameMgr.Get<IMapManager>().GetCertainRoom(roomID).roomStatue = roomStatue;
                _roomStatue = roomStatue;
                break;
            case MapEditorBase.RoomStatue.Chest:
                SetChest(roomID);
                GameMgr.Get<IMapManager>().GetCertainRoom(roomID).roomStatue = roomStatue;
                _roomStatue = roomStatue;
                break;
            case MapEditorBase.RoomStatue.Challenge:
                SetChallenge(roomID);
                GameMgr.Get<IMapManager>().GetCertainRoom(roomID).roomStatue = MapEditorBase.RoomStatue.Empty;
                break;
            default:
                GameMgr.Get<IMapManager>().GetCertainRoom(roomID).roomStatue = roomStatue;
                Debug.Log("Empty!");
                break;
        }
    }
    private void UpdateRoomStatue(int roomID)
    {
        _roomStatue = GameMgr.Get<IMapManager>().GetCertainRoom(roomID).roomStatue;
    }
    /// <summary>
    /// 设置宝箱
    /// </summary>
    /// <param name="roomID"></param>
    private void SetChest(int roomID)
    {
        GameMgr.Get<IMapManager>().GetCertainRoom(roomID).roomStatue = MapEditorBase.RoomStatue.Chest;
        _roomStatue = MapEditorBase.RoomStatue.Chest;
        SceneMonoData _sceneMono = new SceneMonoData();
        _sceneMono.position = GetCenterGround(roomID,1);
        _sceneMono.sceneType = SceneType.Chest;
        _sceneMono.attr = MonoAttribute.None;
        _sceneMono.Params = new List<int>();
        GameMgr.Get<ISceneMonoManager>().AddSceneMono("Chest", _sceneMono);
        Debug.Log("Chest!");
    }
    /// <summary>
    /// 设置挑战
    /// </summary>
    /// <param name="roomID"></param>
    private void SetChallenge(int roomID)
    {
        SceneMonoData _sceneMono = new SceneMonoData();
        _sceneMono.position = GetCenterGround(roomID,-1);
        _sceneMono.sceneType = SceneType.Challenge;
        _sceneMono.attr = MonoAttribute.None;
        _sceneMono.Params = new List<int>();
        GameMgr.Get<ISceneMonoManager>().AddSceneMono("Challenge", _sceneMono);
        Debug.Log("Challenge!");
    }
    /// <summary>
    /// 检查房间敌人状态
    /// </summary>
    /// <param name="roomID"></param>
    private void CheckRoomEnemy(int roomID)
    {
        foreach (var item in GameMgr.Get<IMonoManager>().GetAllMono()._MonoList)
        {
            if (item.Key.Contains("Enemy"))
                return;
        }
        foreach (var item in GameMgr.Get<ISpawnManager>().GetSpawnObjDatas()._spawnData)
        {
            for(int i=0;i< item.Value._spawnData.Count; i++)
            {
                if (item.Value._SpawnDataRecord[i].SpawnedTimes < item.Value._spawnData[i].SpawnCount)
                    return;
            }
        }
        SetChest(roomID);
        RemoveDoors();
    }
    /// <summary>
    /// 移除门
    /// </summary>
    public void RemoveDoors()
    {
        foreach (var item in _doorsName)
            GameMgr.Get<ISceneMonoManager>().RemoveSceneMono(item);
        _doorsName.Clear();
        //战斗结束
        GameMgr.Get<IBattleManager>().EndABattle();
    }
    /// <summary>
    /// 初始化玩家
    /// </summary>
    private void InitPlayerSpawner()
    {
        SpawnData sD = new SpawnData();
        sD.Name = "Player";
        sD.SpawnCount = 1;
        sD.SpawnTimes = 1;
        List<SpawnData> spawnDatas = new List<SpawnData>();
        spawnDatas.Add(sD);

        SpawnObjData spawnObjData = new SpawnObjData();
        spawnObjData.PrefabName = "SpawnerP";
        spawnObjData._spawnData = spawnDatas;
        spawnObjData._SpawnDataRecord = new List<SpawnDataRecord>();
        spawnObjData._SpawnDataRecord.Add(new SpawnDataRecord());
        MapEditorBase.RoomSize roomSize = new MapEditorBase.RoomSize(GameMgr.Get<IMapManager>().GetCertainRoom(_startRoom).roomSize);
        spawnObjData.Pos.x = (roomSize.maxX + roomSize.minX) / 4;
        spawnObjData.Pos.y = (roomSize.maxY + roomSize.minY) / 4;
        GameMgr.Get<ISpawnManager>().AddSpawner("SpawnerP", spawnObjData);
    }
    /// <summary>
    /// 初始化敌人
    /// </summary>
    /// <param name="roomID"></param>
    private void InitEnemy(int roomID)
    {
        GameMgr.Get<IMapManager>().GetCertainRoom(roomID).roomStatue = MapEditorBase.RoomStatue.Enemy;
        int mapID = GameMgr.Get<IMapManager>().GetCertainRoom(roomID).mapID;
        string[] enemies = Data.Instance.TableAgent.GetStrings("AllRoom", mapID.ToString(), "Enemy"); ;
        string[] enemyNum = Data.Instance.TableAgent.GetStrings("AllRoom", mapID.ToString(), "EnemyNum"); ;
        for (int i = 0; i < enemies.Length; i++)
        {
            for (int j = 0; j < int.Parse(enemyNum[i]); j++)
            {
                InitEnemySpawner(1, enemies[i], roomID);
            }
        }
        //战斗开始
        GameMgr.Get<IBattleManager>().CreateABattle();
    }
    /// <summary>
    /// 初始化挑战敌人
    /// </summary>
    /// <param name="roomID"></param>
    private void InitChallengeEnemy(int roomID)
    {
        GameMgr.Get<IMapManager>().GetCertainRoom(roomID).roomStatue = MapEditorBase.RoomStatue.Enemy;
        int mapID = GameMgr.Get<IMapManager>().GetCertainRoom(roomID).mapID;
        string[] enemies = Data.Instance.TableAgent.GetStrings("AllRoom", mapID.ToString(), "ChallengeEnemy"); ;
        string[] enemyNum = Data.Instance.TableAgent.GetStrings("AllRoom", mapID.ToString(), "ChallengeEnemyNum"); ;
        for (int i = 0; i < enemies.Length; i++)
        {
            for (int j = 0; j < int.Parse(enemyNum[i]); j++)
            {
                InitEnemySpawner(1, enemies[i], roomID);
            }
        }
        //战斗开始
        GameMgr.Get<IBattleManager>().CreateABattle();
    }
    /// <summary>
    /// 初始化门
    /// </summary>
    /// <param name="roomID"></param>
    private void InitDoor(int roomID)
    {
        //下上左右方向
        Tuple<int, int>[] dic = { new Tuple<int, int>(-5, 0), new Tuple<int, int>(5, 0), new Tuple<int, int>(0, -5), new Tuple<int, int>(0, 5) };
        Tuple<int, int>[] p = { new Tuple<int, int>(-1, 0), new Tuple<int, int>(1, 0), new Tuple<int, int>(0, -1), new Tuple<int, int>(0, 1) };

        var doors = GameMgr.Get<IMapManager>().GetCertainRoom(roomID).mapDoors;
        for (int i = 0; i < doors.doorPos.Count; i++)
        {
            var pos = doors.doorPos[i];
            int key = GameMgr.Get<IMapManager>().GetHashPosKey((int)(pos.y * 2), (int)(pos.x * 2));
            int doorDic = (int)doors.doorDic[key];
            MapEditorBase.MapWall wall = new MapEditorBase.MapWall();
            wall.param = new List<int>();
            wall.position = new Vector3(pos.x + p[doorDic].Item2, pos.y + p[doorDic].Item1, pos.z);
            switch (doorDic)
            {
                case 0:
                case 1:
                    wall.sceneType = SceneType.HorWall;
                    break;
                case 2:
                case 3:
                    wall.sceneType = SceneType.VerWall;
                    break;
            }
            GameMgr.Get<IMapManager>().GetMapEditor().mapRooms[roomID].mapWalls.Add(wall);
            string name = "";
            if (wall.sceneType == SceneType.HorWall)
                name = "HorDoor";
            if (wall.sceneType == SceneType.VerWall)
                name = "VerDoor"; 
            if (wall.sceneType == SceneType.HorWall)
                AddMonoList(wall, null, name);
            if (wall.sceneType == SceneType.VerWall)
                AddMonoList(wall, null, name);
        }
    }

    /// <summary>
    /// 添加到MonoList
    /// </summary>
    /// <param name="mapWall"></param>
    /// <param name="mapGround"></param>
    /// <param name="name"></param>
    private void AddMonoList(MapEditorBase.MapWall mapWall = null, MapEditorBase.MapGround mapGround = null, string name = "")
    {
        SceneMonoData _sceneMono = new SceneMonoData();
        if (mapGround != null)
        {
            _sceneMono.position = mapGround.position;
            _sceneMono.sceneType = mapGround.sceneType;
            _sceneMono.attr = mapGround.attr;
            _sceneMono.Params = mapGround.param;
        }
        if (mapWall != null)
        {
            _sceneMono.position = mapWall.position;
            _sceneMono.sceneType = mapWall.sceneType;
            _sceneMono.attr = MonoAttribute.None;
            _sceneMono.Params = mapWall.param;
        }
        string temp = GameMgr.Get<ISceneMonoManager>().AddSceneMonoGetName(name, _sceneMono);
        _doorsName.Add(temp);
    }
    /// <summary>
    /// 初始化敌人
    /// </summary>
    /// <param name="num"></param>
    /// <param name="enemyName"></param>
    /// <param name="roomID"></param>
    private void InitEnemySpawner(int num,string enemyName,int roomID)
    {
        SpawnData sD = new SpawnData();
        sD.Name = enemyName;
        sD.SpawnCount = num;
        sD.SpawnTimes = 1;
        List<SpawnData> spawnDatas = new List<SpawnData>();
        spawnDatas.Add(sD);

        SpawnDataRecord sR = new SpawnDataRecord();
        sR.SpawnedTimes = 0;
        sR.LastSpawnTime =0.1f;
        List<SpawnDataRecord> spawnDatasRecord = new List<SpawnDataRecord>();
        spawnDatasRecord.Add(sR);

        SpawnObjData spawnObjData = new SpawnObjData();
        spawnObjData.PrefabName = "Spawner";
        spawnObjData._spawnData = spawnDatas;
        spawnObjData._SpawnDataRecord = spawnDatasRecord;
        spawnObjData.Pos = GetRandomGround(roomID);
        GameMgr.Get<ISpawnManager>().AddSpawner("Spawner", spawnObjData);
    }
    /// <summary>
    /// 初始化敌人
    /// </summary>
    /// <param name="num"></param>
    /// <param name="enemyName"></param>
    /// <param name="roomID"></param>
    public void InitEnemySpawner(int num, string enemyName, Vector3 Pos)
    {
        SpawnData sD = new SpawnData();
        sD.Name = enemyName;
        sD.SpawnCount = num;
        sD.SpawnTimes = 1;
        List<SpawnData> spawnDatas = new List<SpawnData>();
        spawnDatas.Add(sD);
        SpawnObjData spawnObjData = new SpawnObjData();
        spawnObjData.PrefabName = "Spawner";
        spawnObjData._spawnData = spawnDatas;
        spawnObjData._SpawnDataRecord = new List<SpawnDataRecord>();
        spawnObjData._SpawnDataRecord.Add(new SpawnDataRecord());
        spawnObjData.Pos = Pos;
        GameMgr.Get<ISpawnManager>().AddSpawner("Spawner", spawnObjData);
    }


    /// <summary>
    /// 得到该房间随机的一块地砖
    /// </summary>
    /// <param name="roomID"></param>
    /// <returns></returns>
    private Vector3 GetRandomGround(int roomID)
    {
        MapEditorBase.RoomSize roomSize = new MapEditorBase.RoomSize(GameMgr.Get<IMapManager>().GetCertainRoom(roomID).roomSize);
        int distanceY = (roomSize.maxY - roomSize.minY) / 5;
        int rdm = roomSize.minY + UnityEngine.Random.Range(0, distanceY - 1) * 5 + 5;
        var list = GameMgr.Get<IMapManager>().GetMapEditor().mapRooms[roomID].mapGrounds[rdm];
        var pos = GameMgr.Get<IMapManager>().GetCertainGround(rdm, list[list.Count > 1 ? UnityEngine.Random.Range(1, list.Count - 1):0]);
        return pos.position;
    }

    /// <summary>
    /// 得到该房间中间的一块地砖
    /// </summary>
    /// <param name="roomID"></param>
    /// <param name="offset"></param>y轴偏移量
    /// <returns></returns>
    private Vector3 GetCenterGround(int roomID,int offset)
    {
        var grounds = GameMgr.Get<IMapManager>().GetCertainRoom(roomID);
        int tempX = grounds.mapGrounds.Count / 2;
        int y = tempX + offset;
        if (y >= tempX * 2)
            y = tempX * 2 - 1;
        if (y < 0)
            y = 0;
        foreach(var item in grounds.mapGrounds)
        {
            y--;
            if(y < 0)
            {
                y = item.Key;
                break;
            }
        }
        int x = grounds.mapGrounds[y][grounds.mapGrounds[y].Count / 2];
        int key = GameMgr.Get<IMapManager>().GetHashPosKey(y, x);
        return grounds.mapGroundPos[key].position;
    }
    public void ResetPlayerPos()
    {
        var ground = GetCenterGround(_lastRoom,0);
        for (int k = 0; k < GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas.Count; k++)
        {
            GameMgr.Get<IPlayerDataManager>().GetPlayerDatas().PlayerDatas[k].PlayerMono.Position = ground;
        }

    }
}
